
package com.scs.application.modules.msg.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.MsgConsts;
import com.scs.application.consts.SystemProperties;
import com.scs.application.core.msg.enums.MessageType;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UtilCommon;
import com.scs.application.modules.base.entity.Supplier;
import com.scs.application.modules.base.service.SupplierService;
import com.scs.application.modules.msg.entity.PushedRecord;
import com.scs.application.modules.msg.mapper.PushedRecordMapper;
import com.scs.application.modules.msg.request.PushedRecordQueryRequest;
import com.scs.application.modules.msg.service.PushedRecordService;
import com.scs.application.modules.order.entity.PurchaseOrder;
import com.scs.application.modules.upms.dto.vx.VxServerConfig;
import com.scs.application.modules.upms.dto.vx.VxServerPushConfig;
import com.scs.application.modules.upms.dto.vx.VxServerPushFieldConfig;
import com.scs.application.modules.upms.entity.UserWx;
import com.scs.application.modules.upms.service.UserWxService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
* 已推送记录 service 实现
*
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
public class PushedRecordServiceImpl extends BaseServiceImpl<PushedRecordMapper, PushedRecord> implements PushedRecordService, ApplicationRunner {
    private final SupplierService supplierService;
    private final SystemProperties systemProperties;
    private final UserWxService userWxService;

    @Override
    public List<PushedRecord> list(PushedRecordQueryRequest request) {
        List<PushedRecord> list = this.list(getQueryWrapper(request));
        return list;
    }

    @Override
    public IPage<PushedRecord> page(PushedRecordQueryRequest request) {
        IPage page = this.page(request.getPage(), getQueryWrapper(request));
        return page;
    }

    private QueryWrapper<PushedRecord> getQueryWrapper(PushedRecordQueryRequest request){
        return Wrappers.<PushedRecord>query()
                .eq(StringUtils.isNotBlank(request.getSceneCode()), "scene_code", request.getSceneCode())
                .eq(StringUtils.isNotBlank(request.getMsgType()), "msg_type", request.getMsgType())
                .eq(StringUtils.isNotBlank(request.getReceiver()), "receiver", request.getReceiver())
                .between(request.getBeginGmtCreate() != null && request.getEndGmtCreate() != null, "gmt_create", request.getBeginGmtCreate(), request.getEndGmtCreate())
                .eq(StringUtils.isNotBlank(request.getIsSuccess()), "is_success", request.getIsSuccess())
                .orderByDesc("gmt_create");
    }


    private  static  WxMpService wxMpService = null;
    private WxMpService getWxMpService() {
        if (wxMpService != null) {
            return wxMpService;
        }
        //1，配置
        WxMpDefaultConfigImpl wxStorage = new WxMpDefaultConfigImpl();
        wxStorage.setAppId(systemProperties.getWxAppid());
        wxStorage.setSecret(systemProperties.getWxSecret());

        wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        return wxMpService;
    }

    //// 推送消息
    private void sendTemplateMsg(VxServerPushConfig pushConfig,PushedRecord pushedRecord) throws Exception {
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(pushConfig.getToOpenId())
                .templateId(pushConfig.getTempId())
                .build();

        templateMessage.setUrl(pushConfig.getToUrlReal());
        templateMessage.setData(pushedRecord.getVxDataList());
        try {
            getWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (Exception e) {
            throw  e;
        }
    }

    //推送消息内容
    private List<WxMpTemplateData> getVxDataList(VxServerPushConfig pushConfig,JSONObject jsonParam) {
        List<WxMpTemplateData> vxDataList = new ArrayList<>();

        //消息内容
        Date date;
        for(VxServerPushFieldConfig pushFieldConfig : pushConfig.getFieldList()) {
            if (pushFieldConfig.getIsDateAll() != null && pushFieldConfig.getIsDateAll()) {
                date = jsonParam.getDate(pushFieldConfig.getKeyData());
                if (date == null && StringUtils.isNotBlank(pushFieldConfig.getKeyData2())) {
                    date = jsonParam.getDate(pushFieldConfig.getKeyData2());
                }
                if (date != null){
                    vxDataList.add(new WxMpTemplateData(pushFieldConfig.getKeyTemp(), DateUtils.format(date,DateUtils.DEFAULT_PATTER), "#00FFFF"));
                }
                continue;
            }
            vxDataList.add(new WxMpTemplateData(pushFieldConfig.getKeyTemp(), UtilCommon.getStringPre(jsonParam.getString(pushFieldConfig.getKeyData()), 20), "#00FFFF"));
        }
        return vxDataList;
    }

    /**
     * @description: 采购订单下达通知
     * @author: Tai
     **/
    @Async
    @Override
    public void pushVxPoPassAsync(PurchaseOrder purchaseOrder,boolean isTest){
        if (systemProperties.getWxDisabled()) {
            log.error("sendTemplateMsg-已禁用");
            return;
        }
        PushedRecord pushedRecord = new PushedRecord();
        pushedRecord.setMsgType(MessageType.WECHAT.name()).setSceneCode(MsgConsts.SCENE_ORDER_PO_PASS_SUCCESS).setTitle("采购订单下达通知");
        pushedRecord.setReceiverName(purchaseOrder.getSupplierName()).setIsSuccess(GlobalConsts.YES).setGmtCreate(DateUtils.now());
        Supplier supplier = supplierService.getById(purchaseOrder.getSupplierId());
        if (supplier == null) {
            pushedRecord.setIsSuccess(GlobalConsts.NO);
            pushedRecord.setExceptionMsg(String.format("未找到%s供应商信息", purchaseOrder.getSupplierId()));
            this.save(pushedRecord);
            return;
        }
        pushedRecord.setReceiverName(supplier.getName());
        pushedRecord.setReceiver(supplier.getLoginKey());

        JSONObject jsonParam = JSON.parseObject(JSON.toJSONString(purchaseOrder));
        jsonParam.put("poCode",purchaseOrder.getCode());
        jsonParam.put("loginKey",supplier.getLoginKey());
        pushedRecord.setVxDataList(getVxDataList(VxServerConfig.poPass, jsonParam));
        String toUrl =  StrUtil.format(
                VxServerConfig.poPass.getToUrl(),
                systemProperties.getWxServerDomain(),
                System.currentTimeMillis(),
                supplier.getLoginKey(),
                purchaseOrder.getCode()
        );

        if (pushedRecord.getVxDataList() != null) {
            pushedRecord.setContent(StrUtil.format("数据{},跳转地址{}",JSON.toJSONString(pushedRecord.getVxDataList()),toUrl));
        }

        List<String> openIdList = userWxService.getOpenIdByLoginKey(supplier.getLoginKey());
        if (isTest) {
            openIdList = Arrays.asList(systemProperties.getWxServerTestUserOpenId());
        }
        if (ObjectUtil.length(openIdList) == 0) {
            pushedRecord.setIsSuccess(GlobalConsts.NO);
            pushedRecord.setExceptionMsg("未找到该供应商的微信用户绑定关系");
            this.save(pushedRecord);
            return;
        }

        VxServerPushConfig pushConfig;
        PushedRecord pushedRecordOne;
        List<PushedRecord> pushedRecordList = new ArrayList<>();


        for(String openId : openIdList){
            pushedRecordOne = new PushedRecord();
            BeanUtils.copyProperties(pushedRecord, pushedRecordOne);
            pushedRecordOne.setOpenid(openId);
            pushConfig = VxServerConfig.poPass;
            pushConfig.setToOpenId(pushedRecordOne.getOpenid());
            pushConfig.setToUrlReal(toUrl);
            try {
                sendTemplateMsg(pushConfig,pushedRecordOne);
            } catch (Exception e) {
                log.error("sendTemplateMsg-err",e);
                pushedRecordOne.setIsSuccess(GlobalConsts.NO);
                pushedRecordOne.setExceptionMsg(e.getMessage());
            }
            pushedRecordList.add(pushedRecordOne);
        }
        if (pushedRecordList.size() > 0) {
            this.saveBatch(pushedRecordList);
        }
    }

    /**
     * @description: 订单验收成功
     * @author: Tai
     **/
    @Async
    @Override
    public void pushVxPoInAsync(PurchaseOrder purchaseOrder){
        if (systemProperties.getWxDisabled()) {
            log.error("sendTemplateMsg-已禁用");
            return;
        }
        PushedRecord pushedRecord = new PushedRecord();
        pushedRecord.setMsgType(MessageType.WECHAT.name()).setSceneCode(MsgConsts.po_in).setTitle("订单验收通知");
        pushedRecord.setReceiverName(purchaseOrder.getSupplierName()).setIsSuccess(GlobalConsts.YES).setGmtCreate(DateUtils.now());
        Supplier supplier = supplierService.getById(purchaseOrder.getSupplierId());
        if (supplier == null) {
            pushedRecord.setIsSuccess(GlobalConsts.NO);
            pushedRecord.setExceptionMsg(String.format("未找到%s供应商信息", purchaseOrder.getSupplierId()));
            this.save(pushedRecord);
            return;
        }
        pushedRecord.setReceiverName(supplier.getName());
        pushedRecord.setReceiver(supplier.getLoginKey());

        JSONObject jsonParam = JSON.parseObject(JSON.toJSONString(purchaseOrder));
        jsonParam.put("nowTime",pushedRecord.getGmtCreate());
        pushedRecord.setVxDataList(getVxDataList(VxServerConfig.poIn, jsonParam));
        if (pushedRecord.getVxDataList() != null) {
            pushedRecord.setContent(StrUtil.format("数据{}",JSON.toJSONString(pushedRecord.getVxDataList())));
        }

        String toUrl =  StrUtil.format(
                VxServerConfig.poIn.getToUrl(),
                systemProperties.getWxServerDomain(),
                System.currentTimeMillis(),
                supplier.getLoginKey(),
                purchaseOrder.getCode()
        );

        List<String> openIdList = userWxService.getOpenIdByLoginKey(supplier.getLoginKey());
        if (ObjectUtil.length(openIdList) == 0) {
            pushedRecord.setIsSuccess(GlobalConsts.NO);
            pushedRecord.setExceptionMsg("未找到该供应商的微信用户绑定关系");
            this.save(pushedRecord);
            return;
        }

        VxServerPushConfig pushConfig;
        PushedRecord pushedRecordOne;
        List<PushedRecord> pushedRecordList = new ArrayList<>();


        for(String openId : openIdList){
            pushedRecordOne = new PushedRecord();
            BeanUtils.copyProperties(pushedRecord, pushedRecordOne);
            pushedRecordOne.setOpenid(openId);
            pushConfig = VxServerConfig.poIn;
            pushConfig.setToOpenId(pushedRecordOne.getOpenid());
            pushConfig.setToUrlReal(toUrl);
            try {
                sendTemplateMsg(pushConfig,pushedRecordOne);
            } catch (Exception e) {
                log.error("sendTemplateMsg-err",e);
                pushedRecordOne.setIsSuccess(GlobalConsts.NO);
                pushedRecordOne.setExceptionMsg(e.getMessage());
            }
            pushedRecordList.add(pushedRecordOne);
        }
        if (pushedRecordList.size() > 0) {
            this.saveBatch(pushedRecordList);
        }
    }


    private static List<String> spNameEnd = Arrays.asList("医疗器械服务有限公司","投资管理有限公司","医疗器械有限公司","服务有限公司","有限公司","公司");
    /**
     * @description: 通用业务通知
     * @author: Tai
     **/
    @Async
    @Override
    public void pushVxBusCommonAsync(List<String> spIdList,  String hpName,  String taskType,String toPath){
        if (systemProperties.getWxDisabled()) {
            log.error("sendTemplateMsg-已禁用");
            return;
        }
        PushedRecord pushedRecord = new PushedRecord();
        pushedRecord.setMsgType(MessageType.WECHAT.name()).setSceneCode(MsgConsts.bus_common).setTitle("工单处理通知");
        pushedRecord.setIsSuccess(GlobalConsts.YES).setGmtCreate(DateUtils.now());
        List<Supplier> supplierList = supplierService.list(Wrappers.<Supplier>query().in("id",spIdList));
        if (ObjectUtil.length(supplierList) == 0) {
            pushedRecord.setIsSuccess(GlobalConsts.NO);
            pushedRecord.setExceptionMsg(String.format("未找到相关供应商,供应商标识%s", StringUtils.join(spIdList,",")));
            this.save(pushedRecord);
            return;
        }

        List<UserWx> UserWxList = userWxService.list(Wrappers.<UserWx>query().in("login_key",supplierList.stream().map(Supplier::getLoginKey).collect(Collectors.toList())));
        if (ObjectUtil.length(UserWxList) == 0) {
            pushedRecord.setIsSuccess(GlobalConsts.NO);
            pushedRecord.setExceptionMsg(String.format("未找到相关供应商微信用户绑定关系,供应商标识%s", StringUtils.join(spIdList,",")));
            this.save(pushedRecord);
            return;
        }

        JSONObject jsonParam = new JSONObject();
        jsonParam.put("taskTime",pushedRecord.getGmtCreate());
        jsonParam.put("taskType",taskType);
        jsonParam.put("hpName",hpName);
        pushedRecord.setVxDataList(getVxDataList(VxServerConfig.busCommon, jsonParam));
        if (pushedRecord.getVxDataList() != null) {
            pushedRecord.setContent(StrUtil.format("数据{}",JSON.toJSONString(pushedRecord.getVxDataList())));
        }

        Map<String,Supplier> spByLoginKey = supplierList.stream().collect(Collectors.toMap(item -> item.getLoginKey(), item -> item));

        VxServerPushConfig pushConfig;
        PushedRecord pushedRecordOne;
        List<PushedRecord> pushedRecordList = new ArrayList<>();
        String toUrl = "{}/login?tms={}&loginKey={}&toPath={}";
        String toUrlReal  ;
        for(UserWx userWx : UserWxList){
            pushedRecordOne = new PushedRecord();
            BeanUtils.copyProperties(pushedRecord, pushedRecordOne);
            pushedRecordOne.setOpenid(userWx.getOpenId());
            pushedRecordOne.setReceiver(spByLoginKey.get(userWx.getLoginKey()).getLoginKey());
            pushedRecordOne.setReceiverName(spByLoginKey.get(userWx.getLoginKey()).getName());
            // 企业名称
//            jsonParam.put("spName",spByLoginKey.get(userWx.getLoginKey()).getName());
            jsonParam.put("spName",StringUtils.getStrPre(spByLoginKey.get(userWx.getLoginKey()).getName(),spNameEnd));
            pushedRecordOne.setVxDataList(getVxDataList(VxServerConfig.busCommon, jsonParam));
            if (pushedRecordOne.getVxDataList() != null) {
                pushedRecordOne.setContent(StrUtil.format("数据{}",JSON.toJSONString(pushedRecord.getVxDataList())));
            }

            pushConfig = VxServerConfig.busCommon;
            if (StringUtils.isNotBlank(toPath)) {
                toUrlReal =  StrUtil.format(
                        toUrl,
                        systemProperties.getWxServerDomain(),
                        System.currentTimeMillis(),
                        userWx.getLoginKey(),
                        toPath
                );
                pushConfig.setToUrlReal(toUrlReal);
            }

            pushConfig.setToOpenId(pushedRecordOne.getOpenid());
            try {
                sendTemplateMsg(pushConfig,pushedRecordOne);
            } catch (Exception e) {
                log.error("sendTemplateMsg-err",e);
                pushedRecordOne.setIsSuccess(GlobalConsts.NO);
                pushedRecordOne.setExceptionMsg(e.getMessage());
            }
            pushedRecordList.add(pushedRecordOne);
        }
        if (pushedRecordList.size() > 0) {
            this.saveBatch(pushedRecordList);
        }
    }


    /**
     * @description: 通用业务通知
     * @author: Tai
     **/
    @Override
    public WxJsapiSignature getWxConfig(String url){
        try {
            return getWxMpService().createJsapiSignature(url);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
    }

    private void initVxServerPushConfig() {
        //采购订单下达通知
        VxServerConfig.poPass = new VxServerPushConfig();
        VxServerConfig.poPass.setKey("poPass").setTitle("采购订单下达通知").setTitleTrigger("手动采购订单审核通过后、接收到院内采购订单后")
                .setMsgPushOpen(true).setFlagDebug(true).setToUrl("{}/login?tms={}&loginKey={}&toPath=order_confirm_index&poCode={}")
                .setTempId(systemProperties.getWxPoPassTempId())
        ;
        VxServerPushFieldConfig fieldConfig;
        List<VxServerPushFieldConfig> fieldList = new ArrayList<>();
        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("医院名称").setKeyTemp("thing1").setKeyData("hospitalName");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("采购单号").setKeyTemp("character_string2").setKeyData("code");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("采购金额").setKeyTemp("amount4").setKeyData("totalAmount");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("送达日期").setKeyTemp("time5").setKeyData("purchaseDate").setKeyData2("gmtCreate").setIsDateAll(true);
        fieldList.add(fieldConfig);
        VxServerConfig.poPass.setFieldList(fieldList);


        //订单验收通知
        VxServerConfig.poIn = new VxServerPushConfig();
        VxServerConfig.poIn.setKey("poIn").setTitle("订单验收通知").setTitleTrigger("物资系统验收入库审核后").setToUrl("{}/login?tms={}&loginKey={}&toPath=order_report_index&poCode={}")
                .setMsgPushOpen(true)
                .setTempId(systemProperties.getWxPoInTempId())
        ;
        fieldList = new ArrayList<>();
        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("订单编号").setKeyTemp("character_string1").setKeyData("code");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("签收时间").setKeyTemp("time2").setKeyData("nowTime").setIsDateAll(true);
        fieldList.add(fieldConfig);
        VxServerConfig.poIn.setFieldList(fieldList);


        //通用消息提醒
        VxServerConfig.busCommon = new VxServerPushConfig();
        VxServerConfig.busCommon.setKey("busCommon").setTitle("工单处理通知").setTitleTrigger("实时库存推送、高值计费数据推送")
                .setMsgPushOpen(true)
                .setTempId(systemProperties.getWxBusCommonTempId())
        ;
        fieldList = new ArrayList<>();
        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("任务名").setKeyTemp("thing21").setKeyData("taskType");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("院区名称").setKeyTemp("thing60").setKeyData("hpName");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("企业名称").setKeyTemp("thing57").setKeyData("spName");
        fieldList.add(fieldConfig);

        fieldConfig = new VxServerPushFieldConfig();
        fieldConfig.setTitle("上报时间").setKeyTemp("time26").setKeyData("taskTime").setIsDateAll(true);
        fieldList.add(fieldConfig);
        VxServerConfig.busCommon.setFieldList(fieldList);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        this.initVxServerPushConfig();
    }
}
